'''
    动作之客户端简述：
        异步向服务器发出任务请求，等待服务器响应，执行过程中接收服务器发送的进度反馈，任务结束后接收结果反馈

    动作之客户端编写：
        创建动作客户端对象（无需链接回调函数）
        定义发送请求函数：
            定义目标对象和初始化属性 & 等待服务器启动
            异步发送目标对象并链接反馈回调、服务受理状态回调
        执行进度反馈回调函数（以服务器传入的反馈对象作为参数）
        服务受理状态回调（用于监控当服务请求发送后是否被受理）：
            受理状态判断 & 异步获取结果 & 链接完成回调函数
        任务结束回调函数：
            获取结果对象并根据属性判断完成情况
'''


import rclpy
from rclpy.node import Node
from rclpy.action import ActionClient
from my_interfaces.action import MoveCircle


class Action_Circle_Client(Node):
    def __init__(self, name):
        super().__init__(name)
        self.action_client = ActionClient(self, MoveCircle, "action_circle")
        self.get_logger().info(f"Node \"{name}\" is ready!")
    
    def send_request(self, enable:bool = True):
        goal = MoveCircle.Goal()                    # 创建目标对象
        goal.enable = enable                        # 定义目标属性状态
        self.action_client.wait_for_server()        # 等待服务启动
        self.action_client.send_goal_async(goal, self._feedback_callback).add_done_callback(self._accept_callback)     # 异步发送目标对象并链接反馈回调、服务受理状态回调

    def _feedback_callback(self, feedback_msg):     # 执行进度反馈回调
        self.get_logger().info("Current progress: %d" % feedback_msg.feedback.state)


    def _accept_callback(self, future):             # 服务受理状态回调 (异步回调由 future对象作为参数)
        """
        summary:
            用于监控当服务请求发送后是否被受理
        Args:
            future ( obj )
        """        
        accept = future.result()                    # 获取结果对象
        if accept.accepted == False:                # 受理状态判断
            self.get_logger().info('Goal rejected :(')
            return
        self.get_logger().info('Goal accepted :)')
        accept.get_result_async().add_done_callback(self._done_callback)    # 异步获取结果以及链接完成回调函数


    def _done_callback(self, future):               # 完成回调函数 (异步回调由 future对象作为参数)
        response = future.result().result           # 获取结果对象
        if response.finish == True:                 # 判断任务完成情况
            self.get_logger().info("Mission Succeed !")
        else:
            self.get_logger().info("Mission Failed !")
        exit()              # 一次任务结束退出客户端

def main(args=None):
    rclpy.init(args=args)
    node = Action_Circle_Client("action_circle_client")
    node.send_request()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()